using System;
using System.Data;
using System.Data.SqlClient;
using System.Text;
using System.Windows.Forms;
using System.Configuration;
using NNFramework.NeuroLibrary;

namespace HopFieldTest
{
    public partial class frmMain : Form
    {
        private const string STR_CONN_STR = "GeneralExample";
        private clsLayer<int, int> mlhnMonoLayer;
        private DataTable mdtbExamples;
        private DataTable mdtbKeys;
        private DataTable mdtbResults;
        private clsNetwork<int, int, int> mntkNetwork;

        public frmMain()
        {
            InitializeComponent();
        }

        #region NN Functions Section

        /// <summary>
        /// Creates the basic Network Structure, Recives 60 inputs and outputs 1 result
        /// </summary>
        private void CreateNetwork()
        {
            //creates the network
            mntkNetwork = new clsNetwork<int, int, int>(clsLearningFunctions<int, int, int>.LomasResearh);
            //initializes the layer
            mlhnMonoLayer = new clsLayer<int, int>(LayerType.HiddenLayer, 0, LayerArchitecture.FullLateralNoRecursive);
            //sets the layer as the input and output layer
            mntkNetwork.AddInputLayer(mlhnMonoLayer);
            mntkNetwork.AddOutputLayer(mlhnMonoLayer);
            clsNeuron<int, int> cnfNeuron;
            Random rndGen;
            for (int i = 0; i < 60; i++)
            {
                //add one neuron per input
                rndGen = new Random(i);
                cnfNeuron = new clsNeuron<int, int>(clsActivationFunctions.StairFunction, mntkNetwork);
                cnfNeuron.AddDendrite(0, rndGen.NextDouble());
                mlhnMonoLayer.AddNeuron(cnfNeuron);                
            }

            //links the neurons
            for (int i = 0; i < 60; i++)
            {
                for (int j = 0; j < 60; j++)
                {
                    if (i != j)
                    {
                        mlhnMonoLayer.Neurons[i].AddDendrite(mlhnMonoLayer.Neurons[j], mlhnMonoLayer.Neurons[j].Axon);                       
                    }                    
                }                
            }
        }       


        /// <summary>
        /// Loads the examples into the Neural Network and then gets the results into a DataTable called mdtbResults
        /// </summary>
        private void GetResults()
        {
            if (mdtbExamples.Rows.Count > 0)
            {
                //for (int i = 0; i < 30 i++) 
                for (int i = 0; i < mdtbExamples.Rows.Count; i++)
                {
                    for (int j = 0; j < 60; j++)
                    {
                        mlhnMonoLayer.Neurons[j].Dendrites[0] = Convert.ToInt16(mdtbExamples.Rows[i][j]);
                    }

                    for (int j = 0; j < 60; j++)
                    {
                        mdtbResults.Rows[i][j] = mlhnMonoLayer.Neurons[j].Axon;
                    }
                }
            }
            else
            {
                MessageBox.Show("The examples still hasn't been loaded, so you can't get results.");
            }
            
        }      

        #endregion

        private void LoadExamples()
        {
            SqlConnection sqlCon = new SqlConnection(ConfigurationManager.ConnectionStrings[STR_CONN_STR].ConnectionString);
            SqlDataAdapter sqlAda = new SqlDataAdapter("select * from vExamples", sqlCon);
            mdtbExamples = new DataTable();
            mdtbKeys = new DataTable();
            sqlAda.Fill(mdtbExamples);
            sqlAda.SelectCommand.CommandText = "select * from vExamples where [Key] = 1";
            sqlAda.Fill(mdtbKeys);
            mdtbResults = mdtbExamples.Copy();            
        }

        

        private void btnCreate_Click(object sender, EventArgs e)
        {           
            CreateNetwork();
            //After loads the Examples too, now a separate button is created for this task
        }

        private void btnGetResults_Click(object sender, EventArgs e)
        {           
            GetResults();
            cmbResult.DataSource = mdtbResults;
            mntkNetwork.Examples = mdtbExamples;
            sfdFiles.Title = "Save Neural Network Files: Mono Layer";
            sfdFiles.FileName = @"d:\Hopfield.xml";
            sfdFiles.ShowDialog();
            mlhnMonoLayer.SerializeMeToXml(sfdFiles.FileName);
            sfdFiles.Title = "Save Neural Network Files: Neural Network to XML File";
            sfdFiles.FileName = @"d:\HopfieldNetwork.xml";
            sfdFiles.ShowDialog();
            mntkNetwork.SerializeMeToXml(sfdFiles.FileName);
            sfdFiles.Title = "Save Neural Network Files: Neural Network to Binary File";
            sfdFiles.FileName = @"d:\HopfieldNetwork.bin";
            sfdFiles.ShowDialog();
            mntkNetwork.SerializeMeToBin(sfdFiles.FileName);
        }

        private void cmbExamples_SelectedIndexChanged(object sender, EventArgs e)
        {
            dspExample.SetDisplay(mdtbExamples.Rows[cmbExamples.SelectedIndex]);
            lblExam.Text = cmbExamples.SelectedValue.ToString();
        }

        private void cmbResult_SelectedIndexChanged(object sender, EventArgs e)
        {
            dspLearned.SetDisplay(mdtbResults.Rows[cmbResult.SelectedIndex]);
            lblNumber.Text = cmbResult.SelectedValue.ToString();
        }

        private void btnLearn_Click(object sender, EventArgs e)
        {
            LoadExamples();
            DateTime dtmStart = DateTime.Now;
            for (int i = 0; i < 100; i++)
            {                            
                mntkNetwork.TrainMeOnce();
            }
            MessageBox.Show("Total Train Time: " + ((dtmStart - DateTime.Now)));
            
        }

        private void cmbFuzzy_SelectedIndexChanged(object sender, EventArgs e)
        {
            dspFuzzy.SetDisplay(mdtbExamples.Rows[cmbFuzzy.SelectedIndex]);
        }

        private void btnQuery_Click(object sender, EventArgs e)
        {
            int[] intPattern = dspFuzzy.GetDisplay();
            int[] intResult = new int[60];
            
            for (int i = 0; i < 60; i++)
            {
                mlhnMonoLayer.Neurons[i].Dendrites[0] = intPattern[i];                
            }

            for (int i = 0; i < 60; i++)
            {
                intResult[i] = mlhnMonoLayer.Neurons[i].Axon;
            }
            dspResult.SetDisplay(intResult);
        }

        private void btnInsert_Click(object sender, EventArgs e)
        {
            SqlConnection sqlCon = new SqlConnection(ConfigurationManager.ConnectionStrings[STR_CONN_STR].ConnectionString);
            SqlCommand sqlCmd = new SqlCommand("", sqlCon);
            int[] intResult = dspFuzzy.GetDisplay();
            StringBuilder strCmd = new StringBuilder("insert into Import$(");
            for (int i = 0; i < 60; i++)
            {
                strCmd.Append("I");
                strCmd.Append(i);
                strCmd.Append(", ");
            }
            strCmd.Append("O1, [Key]) values(");

            for (int i = 0; i < 60; i++)
            {
                strCmd.Append(intResult[i]);
                strCmd.Append(", ");
            }
            strCmd.Append(cmbFuzzy.Text);
            strCmd.Append(", 0)");
            sqlCmd.CommandText = strCmd.ToString();
            sqlCon.Open();
            sqlCmd.ExecuteNonQuery();
            sqlCon.Close();
        }

        private void btnLoad_Click(object sender, EventArgs e)
        {
            ofdFile.FileName = @"d:\HopfieldNetwork.bin";
            ofdFile.Title = "Open Neural Network Binary File";
            if (ofdFile.ShowDialog() == DialogResult.OK)
            {
                LoadExamplesFromDB();
                mntkNetwork = clsNetwork<int, int, int>.LoadNetworkFromBin(ofdFile.FileName);
                mlhnMonoLayer = mntkNetwork.InputLayers[0];
            }
        }

        private void btnDbLoad_Click(object sender, EventArgs e)
        {
            LoadExamplesFromDB();
        }

        /// <summary>
        /// Loads the network examples from db and refresh the combos
        /// </summary>
        private void LoadExamplesFromDB()
        {
            LoadExamples();
            cmbExamples.DataSource = mdtbExamples;
            cmbFuzzy.DataSource = mdtbExamples;
        }

        private void chbFuzzy_CheckedChanged(object sender, EventArgs e)
        {
            if (chbFuzzy.Checked)
            {
                dspFuzzy.DarkenMe();
            }
            else
            {
                dspFuzzy.ToNomal();
            }
        }

        private void chbBase_CheckedChanged(object sender, EventArgs e)
        {
            if (chbBase.Checked)
            {
                dspExample.DarkenMe();
            }
            else
            {
                dspExample.ToNomal();
            }
        }

        private void chbLearned_CheckedChanged(object sender, EventArgs e)
        {
            if (chbLearned.Checked)
            {
                dspLearned.DarkenMe();
            }
            else
            {
                dspLearned.ToNomal();
            }
        }

        private void chbResult_CheckedChanged(object sender, EventArgs e)
        {
            if (chbResult.Checked)
            {
                dspResult.DarkenMe();
            }
            else
            {
                dspResult.ToNomal();
            }
        }

        
    }
}